package com.scale.service.voice.service.impl;

import com.alibaba.dashscope.aigc.multimodalconversation.AudioParameters;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.scale.service.voice.service.StreamTtsService;
import com.scale.service.voice.service.TaskProgressService;
import com.scale.service.voice.service.VoiceFileStorageService;
import io.reactivex.Flowable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.util.Base64;

/**
 * 流式语音合成服务实现类
 * @author crp
 * @since 2025-01-26
 */
@Service
public class StreamTtsServiceImpl implements StreamTtsService {
    
    @Value("${dashscope.api-key:}")
    private String dashscopeApiKey;
    
    @Value("${voice.tts.test-mode:false}")
    private boolean testMode;
    
    @Value("${voice.tts.mock-response:false}")
    private boolean mockResponse;
    
    @Autowired
    private TaskProgressService taskProgressService;
    
    @Autowired
    private VoiceFileStorageService voiceFileStorageService;
    
    @Override
    public String processTtsStream(String taskId, String text, String voiceType, String language) throws Exception {
        // 检查是否启用测试模式
        if (testMode || mockResponse) {
            System.out.println("🔧 TTS测试模式启用，返回模拟语音文件");
            return generateMockTTSResponse(text, taskId);
        }
        
        // 添加API额度检查和降级处理
        try {
            return processRealTTS(taskId, text, voiceType, language);
        } catch (Exception e) {
            if (e.getMessage() != null && (e.getMessage().contains("FreeTierOnly") || 
                e.getMessage().contains("free tier") || e.getMessage().contains("exhausted"))) {
                System.err.println("⚠️ 阿里云TTS免费额度用完，使用降级方案");
                return generateMockTTSResponse(text, taskId);
            }
            throw e; // 重新抛出其他异常
        }
    }
    
    /**
     * 真实的TTS处理逻辑
     */
    private String processRealTTS(String taskId, String text, String voiceType, String language) throws Exception {
        MultiModalConversation conv = new MultiModalConversation();
        
        // 映射语言代码到阿里云TTS支持的语言类型
        String languageType = mapLanguageToTtsType(language);
        System.out.println("TTS语言映射: " + language + " -> " + languageType);
        
        MultiModalConversationParam param = MultiModalConversationParam.builder()
                .apiKey(dashscopeApiKey)
                .model("qwen3-tts-flash")
                .text(text)
                .voice(getVoiceByType(voiceType))
                .languageType(languageType)
                .build();
        
        Flowable<MultiModalConversationResult> resultFlowable = conv.streamCall(param);
        ByteArrayOutputStream audioBuffer = new ByteArrayOutputStream();
        
        final int[] chunkCount = {0};
        final int[] totalBytes = {0};
        resultFlowable.blockingForEach(item -> {
            try {
                // 🔧 改进TTS数据处理：确保数据完整性
                if (item.getOutput() != null && item.getOutput().getAudio() != null) {
                    String base64Data = item.getOutput().getAudio().getData();
                    if (base64Data != null && !base64Data.trim().isEmpty()) {
                        byte[] audioBytes = Base64.getDecoder().decode(base64Data);
                        audioBuffer.write(audioBytes);
                        totalBytes[0] += audioBytes.length;
                        
                        chunkCount[0]++;
                        // 每10个数据块推送一次进度，减少日志输出
                        if (chunkCount[0] % 10 == 0) {
                            System.out.println("TTS处理进度: 已处理 " + chunkCount[0] + " 个数据块, 累计 " + totalBytes[0] + " 字节");
                            taskProgressService.updateProgress(taskId, "TTS", 80, 
                                "正在生成语音回复... (" + chunkCount[0] + " 块)");
                        }
                    } else {
                        System.out.println("⚠️ TTS数据块为空，跳过");
                    }
                } else {
                    System.out.println("⚠️ TTS响应数据结构异常，跳过");
                }
                
            } catch (Exception e) {
                System.err.println("❌ TTS数据块处理失败: " + e.getMessage());
                throw new RuntimeException("TTS处理失败: " + e.getMessage(), e);
            }
        });
        
        System.out.println("TTS处理完成: 总共处理了 " + chunkCount[0] + " 个数据块, 总字节数: " + totalBytes[0]);
        
        // 保存音频文件
        byte[] audioBytes = audioBuffer.toByteArray();
        if (audioBytes.length == 0) {
            throw new RuntimeException("TTS音频数据为空，无法生成语音文件");
        }
        
        // 🔧 阿里云TTS返回的是原始PCM数据，需要添加WAV头部
        System.out.println("🎵 检查音频格式: " + getAudioHeaderInfo(audioBytes));
        if (!isValidAudioData(audioBytes)) {
            System.out.println("⚠️ 音频数据不是标准WAV格式，添加WAV头部");
            audioBytes = addWavHeader(audioBytes);
            System.out.println("✅ 已添加WAV头部，新文件大小: " + audioBytes.length + " 字节");
            System.out.println("🎵 修复后音频格式: " + getAudioHeaderInfo(audioBytes));
        } else {
            System.out.println("✅ 音频数据已是标准WAV格式");
        }
        
        String base64Audio = Base64.getEncoder().encodeToString(audioBytes);
        
        // 🔧 添加音频数据验证和格式检查
        System.out.println("🎵 音频数据详情:");
        System.out.println("   - 原始字节数: " + audioBytes.length);
        System.out.println("   - Base64长度: " + base64Audio.length());
        System.out.println("   - 音频头信息: " + getAudioHeaderInfo(audioBytes));
        
        String dataUrl = "data:audio/wav;base64," + base64Audio;
        String voiceUrl = voiceFileStorageService.storeVoiceFile(dataUrl, "wav", null);
        
        System.out.println("✅ TTS音频文件已保存: " + voiceUrl + ", 大小: " + audioBytes.length + " 字节");
        System.out.println("🎵 音频文件可通过以下URL访问: " + voiceUrl);
        System.out.println("🎵 Data URL长度: " + dataUrl.length() + " 字符");
        
        return voiceUrl;
    }
    
    private AudioParameters.Voice getVoiceByType(String voiceType) {
        switch (voiceType.toLowerCase()) {
            case "male": return AudioParameters.Voice.CHERRY;
            case "female": return AudioParameters.Voice.CHERRY;
            default: return AudioParameters.Voice.CHERRY;
        }
    }
    
    /**
     * 生成模拟TTS响应 (用于测试模式或API额度用完时的降级处理)
     */
    private String generateMockTTSResponse(String text, String taskId) throws Exception {
        System.out.println("🎭 生成模拟TTS响应，文本: " + text);
        
        // 模拟TTS处理进度
        taskProgressService.updateProgress(taskId, "TTS", 70, "正在生成语音回复(模拟模式)...");
        Thread.sleep(500); // 模拟处理时间
        
        taskProgressService.updateProgress(taskId, "TTS", 90, "语音生成完成(模拟模式)...");
        Thread.sleep(300);
        
        // 生成一个简单的模拟音频文件 (静音的WAV文件头部)
        String mockAudioBase64 = generateMockAudioData();
        String mockAudioData = "data:audio/wav;base64," + mockAudioBase64;
        
        // 通过文件存储服务保存模拟音频文件
        String voiceUrl = voiceFileStorageService.storeVoiceFile(mockAudioData, "wav", null);
        
        System.out.println("🎭 模拟TTS文件已生成: " + voiceUrl);
        return voiceUrl;
    }
    
    /**
     * 生成模拟音频数据 (1秒静音WAV文件)
     */
    private String generateMockAudioData() {
        // 简单的1秒静音WAV文件的Base64编码
        // WAV头部(44字节) + 1秒44100Hz单声道16位静音数据
        byte[] wavHeader = {
            // RIFF头部
            0x52, 0x49, 0x46, 0x46, // "RIFF"
            0x24, (byte) 0xAA, 0x01, 0x00, // 文件大小 (108580字节)
            0x57, 0x41, 0x56, 0x45, // "WAVE"
            
            // fmt子块
            0x66, 0x6D, 0x74, 0x20, // "fmt "
            0x10, 0x00, 0x00, 0x00, // fmt子块大小 (16字节)
            0x01, 0x00, // 音频格式 (PCM)
            0x01, 0x00, // 声道数 (1)
            0x44, (byte) 0xAC, 0x00, 0x00, // 采样率 (44100Hz)
            (byte) 0x88, 0x58, 0x01, 0x00, // 字节率
            0x02, 0x00, // 块对齐
            0x10, 0x00, // 位深度 (16位)
            
            // data子块头部
            0x64, 0x61, 0x74, 0x61, // "data"
            0x00, (byte) 0xAA, 0x01, 0x00 // 数据大小 (108544字节)
        };
        
        // 1秒静音数据 (44100 samples * 2 bytes = 88200 bytes)
        byte[] silenceData = new byte[88200];
        
        // 合并头部和数据
        byte[] fullWav = new byte[wavHeader.length + silenceData.length];
        System.arraycopy(wavHeader, 0, fullWav, 0, wavHeader.length);
        System.arraycopy(silenceData, 0, fullWav, wavHeader.length, silenceData.length);
        
        return Base64.getEncoder().encodeToString(fullWav);
    }
    
    /**
     * 验证音频数据是否有效
     */
    /**
     * 获取音频头信息
     */
    private String getAudioHeaderInfo(byte[] audioBytes) {
        if (audioBytes == null || audioBytes.length < 44) {
            return "数据不足(需要至少44字节WAV头部)";
        }
        
        StringBuilder info = new StringBuilder();
        
        // 检查RIFF标识
        String riffHeader = new String(audioBytes, 0, 4);
        info.append("RIFF标识: ").append(riffHeader);
        
        if ("RIFF".equals(riffHeader)) {
            // 文件大小
            int fileSize = getIntFromBytes(audioBytes, 4) + 8;
            info.append(", 文件大小: ").append(fileSize);
            
            // WAVE标识
            String waveHeader = new String(audioBytes, 8, 4);
            info.append(", WAVE标识: ").append(waveHeader);
            
            // 如果是有效的WAV文件，获取更多信息
            if ("WAVE".equals(waveHeader) && audioBytes.length >= 44) {
                try {
                    int sampleRate = getIntFromBytes(audioBytes, 24);
                    int channels = getShortFromBytes(audioBytes, 22);
                    int bitsPerSample = getShortFromBytes(audioBytes, 34);
                    
                    info.append(", 采样率: ").append(sampleRate)
                        .append("Hz, 声道: ").append(channels)
                        .append(", 位深: ").append(bitsPerSample).append("bit");
                } catch (Exception e) {
                    info.append(", 解析WAV头部失败: ").append(e.getMessage());
                }
            }
        } else {
            // 检查前几个字节
            info.append(", 前8字节: ");
            for (int i = 0; i < Math.min(8, audioBytes.length); i++) {
                info.append(String.format("%02X ", audioBytes[i] & 0xFF));
            }
        }
        
        return info.toString();
    }
    
    /**
     * 从字节数组中读取32位整数（小端序）
     */
    private int getIntFromBytes(byte[] bytes, int offset) {
        return (bytes[offset] & 0xFF) |
               ((bytes[offset + 1] & 0xFF) << 8) |
               ((bytes[offset + 2] & 0xFF) << 16) |
               ((bytes[offset + 3] & 0xFF) << 24);
    }
    
    /**
     * 从字节数组中读取16位整数（小端序）
     */
    private short getShortFromBytes(byte[] bytes, int offset) {
        return (short) ((bytes[offset] & 0xFF) |
                       ((bytes[offset + 1] & 0xFF) << 8));
    }
    
    /**
     * 为原始音频数据添加WAV头部
     * 🔧 参考阿里云官方TTS文档调整音频参数
     */
    private byte[] addWavHeader(byte[] audioData) {
        // 🔧 根据阿里云TTS实际返回格式：24000Hz, 16位, 单声道
        int sampleRate = 24000;  // 修改为24000Hz（与官方示例一致）
        int channels = 1;
        int bitsPerSample = 16;
        int byteRate = sampleRate * channels * bitsPerSample / 8;
        int blockAlign = channels * bitsPerSample / 8;
        
        // 计算文件大小
        int dataSize = audioData.length;
        int fileSize = 36 + dataSize;
        
        ByteArrayOutputStream wavFile = new ByteArrayOutputStream();
        
        try {
            // RIFF头部
            wavFile.write("RIFF".getBytes());
            wavFile.write(intToBytes(fileSize));
            wavFile.write("WAVE".getBytes());
            
            // fmt子块
            wavFile.write("fmt ".getBytes());
            wavFile.write(intToBytes(16)); // fmt子块大小
            wavFile.write(shortToBytes((short) 1)); // 音频格式 (PCM)
            wavFile.write(shortToBytes((short) channels)); // 声道数
            wavFile.write(intToBytes(sampleRate)); // 采样率
            wavFile.write(intToBytes(byteRate)); // 字节率
            wavFile.write(shortToBytes((short) blockAlign)); // 块对齐
            wavFile.write(shortToBytes((short) bitsPerSample)); // 位深
            
            // data子块
            wavFile.write("data".getBytes());
            wavFile.write(intToBytes(dataSize));
            wavFile.write(audioData);
            
        } catch (Exception e) {
            System.err.println("❌ 添加WAV头部失败: " + e.getMessage());
            return audioData; // 返回原始数据
        }
        
        return wavFile.toByteArray();
    }
    
    /**
     * 整数转小端序字节数组
     */
    private byte[] intToBytes(int value) {
        return new byte[] {
            (byte) (value & 0xFF),
            (byte) ((value >> 8) & 0xFF),
            (byte) ((value >> 16) & 0xFF),
            (byte) ((value >> 24) & 0xFF)
        };
    }
    
    /**
     * 短整数转小端序字节数组
     */
    private byte[] shortToBytes(short value) {
        return new byte[] {
            (byte) (value & 0xFF),
            (byte) ((value >> 8) & 0xFF)
        };
    }
    
    private boolean isValidAudioData(byte[] audioBytes) {
        if (audioBytes == null || audioBytes.length < 44) {
            return false; // WAV文件至少需要44字节的头部
        }
        
        // 检查WAV文件头部标识
        if (audioBytes.length >= 4) {
            String header = new String(audioBytes, 0, 4);
            if ("RIFF".equals(header)) {
                return true; // RIFF/WAV格式
            }
        }
        
        // 检查是否是有效的音频数据（非全零）
        boolean hasNonZeroData = false;
        for (byte b : audioBytes) {
            if (b != 0) {
                hasNonZeroData = true;
                break;
            }
        }
        
        // 🔧 修复：严格检查WAV格式，只有真正的WAV文件才返回true
        if (audioBytes.length >= 4) {
            String header = new String(audioBytes, 0, 4);
            boolean isRiff = "RIFF".equals(header);
            if (!isRiff) {
                System.out.println("🔍 检测到原始PCM数据，需要添加WAV头部");
                return false; // 原始PCM数据，需要添加WAV头部
            }
            return isRiff && hasNonZeroData;
        }
        
        return false; // 数据太短，不是有效格式
    }
    
    /**
     * 映射语言代码到阿里云TTS支持的语言类型
     */
    private String mapLanguageToTtsType(String language) {
        if (language == null) {
            return "Auto";
        }
        
        switch (language.toLowerCase()) {
            case "zh":
            case "zh-cn":
            case "chinese":
                return "Chinese";
            case "en":
            case "english":
                return "English";
            case "ja":
            case "japanese":
                return "Japanese";
            case "ko":
            case "korean":
                return "Korean";
            case "fr":
            case "french":
                return "French";
            case "de":
            case "german":
                return "German";
            case "es":
            case "spanish":
                return "Spanish";
            case "it":
            case "italian":
                return "Italian";
            case "pt":
            case "portuguese":
                return "Portuguese";
            case "ru":
            case "russian":
                return "Russian";
            default:
                return "Auto"; // 自动检测
        }
    }
}
